#include "SoftUSART.h"

/*常用寄存器操作封装*/
#define TIM_ON(_TIM_) ((_TIM_)->CR1 |= TIM_CR1_CEN)
#define TIM_OFF(_TIM_) ((_TIM_)->CR1 &=~ TIM_CR1_CEN)
#define TIM_SET_CNT(_TIM_,_VALUE_) ((_TIM_)->CNT = (_VALUE_))
#define TIM_SET_PSC(_TIM_,_VALUE_) ((_TIM_)->PSC = (_VALUE_))
#define TIM_SET_ARR(_TIM_,_VALUE_) ((_TIM_)->ARR = (_VALUE_))
#define TIM_UP_IT_ON(_TIM_) ((_TIM_)->DIER |= TIM_DIER_UIE)
#define TIM_UP_IT_OFF(_TIM_) ((_TIM_)->DIER &=~ TIM_DIER_UIE)
#define TIM_UP_ITSTATE_CLR(_TIM_) ((_TIM_)->SR &=~ TIM_SR_UIF)
#define TIM_UP_ITSTATE_SET(_TIM_) ((_TIM_)->SR |= TIM_SR_UIF)

#define RX_IT_ON() (EXTI->IMR |= EXTI_IMR_IM10)
#define RX_IT_OFF() (EXTI->IMR &=~ EXTI_IMR_IM10)

SoftUSART_TypeDef SoftUSART1 = {0};

void PORT_CLK(GPIO_TypeDef *PORT,FunctionalState State)
{
	switch((uint32_t)PORT)
	{
		case GPIOA_BASE:{if(State)__HAL_RCC_GPIOA_CLK_ENABLE();else __HAL_RCC_GPIOA_CLK_DISABLE();break;}
		case GPIOB_BASE:{if(State)__HAL_RCC_GPIOB_CLK_ENABLE();else __HAL_RCC_GPIOB_CLK_DISABLE();break;}
		case GPIOC_BASE:{if(State)__HAL_RCC_GPIOC_CLK_ENABLE();else __HAL_RCC_GPIOC_CLK_DISABLE();break;}
		case GPIOD_BASE:{if(State)__HAL_RCC_GPIOD_CLK_ENABLE();else __HAL_RCC_GPIOD_CLK_DISABLE();break;}
		case GPIOE_BASE:{if(State)__HAL_RCC_GPIOE_CLK_ENABLE();else __HAL_RCC_GPIOE_CLK_DISABLE();break;}
		case GPIOF_BASE:{if(State)__HAL_RCC_GPIOF_CLK_ENABLE();else __HAL_RCC_GPIOF_CLK_DISABLE();break;}
		default:break;
	}
}

/*示例初始化函数*/
SoftUSART_Status_Def SoftUSART_Init(SoftUSART_TypeDef *SoftUSART,uint32_t BaudRate,GPIO_TypeDef *RX_PORT,uint16_t RX_PIN,
									GPIO_TypeDef *TX_PORT,uint16_t TX_PIN,TIM_TypeDef *TIM)
{
	PORT_CLK(RX_PORT,ENABLE);
	PORT_CLK(TX_PORT,ENABLE);
	SoftUSART->Status = SoftUSART_Init_Config(SoftUSART,BaudRate,DataBit_8Bit,Parity_None,StopBit_1Bit);
	SoftUSART->Status = SoftUSART_Init_GPIO(SoftUSART,RX_PORT,RX_PIN,TX_PORT,TX_PIN);
	SoftUSART->Status = SoftUSART_Init_TIM(SoftUSART,TIM);
	SoftUSART->Status = SoftUSART_Init_IT(SoftUSART,0,1);
	

	return Status_OK;

}

/*初始化函数*/
/*
	函数名称：SoftUSART_Init_GPIO
	函数功能：初始化软串口IO口配置
 */
SoftUSART_Status_Def SoftUSART_Init_GPIO(SoftUSART_TypeDef *SoftUSART,GPIO_TypeDef *RX_PORT,uint16_t RX_PIN,GPIO_TypeDef *TX_PORT,uint16_t TX_PIN)
{
	GPIO_InitTypeDef GI1 = {0};
	
	/*传入参数校验*/
	
	
	PIN_SET(TX_PORT,TX_PIN);
	
	GI1.Mode = GPIO_MODE_IT_FALLING;
	GI1.Pull = GPIO_PULLUP;
	GI1.Speed = GPIO_SPEED_FREQ_HIGH;
	GI1.Pin = RX_PIN;
	HAL_GPIO_Init(RX_PORT,&GI1);
	
	GI1.Mode = GPIO_MODE_OUTPUT_PP;
	GI1.Pull = GPIO_NOPULL;
	GI1.Speed = GPIO_SPEED_FREQ_HIGH;
	GI1.Pin = TX_PIN;
	HAL_GPIO_Init(TX_PORT,&GI1);
	
	SoftUSART->RX_PORT = RX_PORT;
	SoftUSART->TX_PORT = TX_PORT;
	SoftUSART->RX_PIN = RX_PIN;
	SoftUSART->TX_PIN = TX_PIN;
	
	return Status_OK;
}

/*
	函数名称：SoftUSART_Init_TIM
	函数功能：初始化软串口定时器
*/
SoftUSART_Status_Def SoftUSART_Init_TIM(SoftUSART_TypeDef *SoftUSART,TIM_TypeDef *TIM)
{
	if(TIM == NULL)
		TIM = TIM1;

//	temp1 = ((100*10000)/SoftUSART->BaudRate);
//	temp1 *= ((SystemCoreClock/1000000)/8);
//	temp1 -= 1;

	TIM_OFF(TIM);
	//TIM_SET_CNT(TIM, 0);  //清除计数值
	//TIM_SET_PSC(TIM,(SystemCoreClock/1000000)-1);
	TIM_SET_PSC(TIM,7);
	// TIM_SET_ARR(TIM, (SystemCoreClock/1000000));  //设定计数周期
	TIM_SET_ARR(TIM,SoftUSART->BitTime);
	//TIM_SET_ARR(TIM,(((1000000/SoftUSART->BaudRate))-1));
	//TIM_SET_ARR(TIM,temp1);
	//TIM_SET_ARR(TIM,4799);
	TIM_UP_ITSTATE_CLR(TIM);
	TIM_UP_IT_ON(TIM);  //开启更新中断

	SoftUSART->TIM = TIM;
	return Status_OK;
}

/*
	函数名称：SoftUSART_Init_IT
	函数功能：初始化软串口中断及优先级
*/
SoftUSART_Status_Def SoftUSART_Init_IT(SoftUSART_TypeDef *SoftUSART,uint16_t EXTI_Prio,uint16_t TIM_Prio)
{
	/*传入参数校验*/
	if(SoftUSART->TIM == NULL)
		return Status_Error;
	
	NVIC_SetPriority(EXTI4_15_IRQn,EXTI_Prio);
	NVIC_SetPriority(TIM2_IRQn,TIM_Prio);
	NVIC_EnableIRQ(EXTI4_15_IRQn);
	NVIC_EnableIRQ(TIM2_IRQn);
	RX_IT_ON();
	
	return Status_OK;
}

/*
	函数名称：SoftUSART_Init_Config
	函数功能：初始化软串口参数
*/
SoftUSART_Status_Def SoftUSART_Init_Config(SoftUSART_TypeDef *SoftUSART,uint32_t BaudRate,SoftUSART_DataBit_Def DataBit,SoftUSART_Parity_Def Parity,SoftUSART_StopBit_Def StopBit)
{
	/*传入参数校验*/
	if(BaudRate == 0)
		BaudRate = 9600;
	
	SoftUSART->BaudRate = BaudRate;
	SoftUSART->DataBit = DataBit;
	SoftUSART->Parity = Parity;
	SoftUSART->StopBit = StopBit;
	SoftUSART->BitTime = (uint32_t)((1000000.0/(float)SoftUSART->BaudRate)*((float)SystemCoreClock/8000000.0))-1;

	// memset(SoftUSART->RX_Buffer.Buffer,0,sizeof(SoftUSART->RX_Buffer.Buffer));
	// memset(SoftUSART->TX_Buffer.Buffer,0,sizeof(SoftUSART->TX_Buffer.Buffer));

	return Status_OK;
}

SoftUSART_Status_Def SoftUSART_StartRecvConfig(SoftUSART_TypeDef *SoftUSART)
{
	/*如果软串口在发送*/
	if(SoftUSART->TX_Buffer.Flag & Flag_Runing)
	{
		SoftUSART->RX_Buffer.Flag |= Flag_Runing;  //置位运行标志
		SoftUSART->TX_Buffer.Flag &=~ Flag_Runing;  //复位运行标志
		SoftUSART->TX_Buffer.Flag |= Flag_Suspend;  //将发送挂起
	}
	/*如果软串口没在发送且不在接收状态*/
	else if(!(SoftUSART->RX_Buffer.Flag & Flag_Runing))
	{
		SoftUSART->RX_Buffer.Flag |= Flag_Runing;  //置位运行标志
	}
	//TIM_SET_CNT(SoftUSART->TIM,SoftUSART->BitTime - (((uint32_t)(1000000.0/(float)SoftUSART->BaudRate)) & SoftUSART->BitTime));
	TIM_SET_CNT(SoftUSART->TIM,SoftUSART->BitTime);
	TIM_SET_ARR(SoftUSART->TIM,SoftUSART->BitTime);
	TIM_ON(SoftUSART->TIM);  //开启定时器
	return Status_OK; 
}

/*字符串发送*/
uint16_t SoftUSART_Write(SoftUSART_TypeDef *SoftUSART,uint8_t *Dat,uint16_t Dat_Length)
{
	for(uint16_t cnt = 0;cnt < Dat_Length;)
	{
		//如果写入的数据超过定时器那边读取的速度，就等待发送完成
		if(SoftUSART->TX_Buffer.RW_Subtract < sizeof(SoftUSART->TX_Buffer.Buffer))    
		{
			SoftUSART->TX_Buffer.Buffer[SoftUSART->TX_Buffer.Write_Count] = Dat[cnt];
			SoftUSART->TX_Buffer.Write_Count += 1;  //下一个写入
			SoftUSART->TX_Buffer.RW_Subtract += 1;  //
			if(SoftUSART->TX_Buffer.RW_Subtract > 0)  //启动传输
			{
				SoftUSART->TX_Buffer.Flag |= Flag_Runing;
				//TIM_SET_CNT(SoftUSART->TIM,0);
				TIM_SET_ARR(SoftUSART->TIM,SoftUSART->BitTime);
				TIM_ON(SoftUSART->TIM);  //开启定时器
			}
			if(SoftUSART->TX_Buffer.Write_Count >= sizeof(SoftUSART->TX_Buffer.Buffer))
			{
				SoftUSART->TX_Buffer.Write_Count = 0;
			}
			cnt += 1;
		}
		else
		{
			
		}
	}
	return Status_OK;
}

/*字节发送*/
uint8_t SoftUSART_WriteByte(SoftUSART_TypeDef *SoftUSART,uint8_t Dat)
{
	uint8_t ret = 0;
	if(SoftUSART->TX_Buffer.RW_Subtract < sizeof(SoftUSART->TX_Buffer.Buffer))    
	{
		SoftUSART->TX_Buffer.Buffer[SoftUSART->TX_Buffer.Write_Count] = Dat;
		SoftUSART->TX_Buffer.Write_Count += 1;  //下一个写入
		SoftUSART->TX_Buffer.RW_Subtract += 1;  //
		if(SoftUSART->TX_Buffer.RW_Subtract > 0)  //启动传输
		{
			SoftUSART->TX_Buffer.Flag |= Flag_Runing;
			TIM_SET_ARR(SoftUSART->TIM,SoftUSART->BitTime);
			TIM_ON(SoftUSART->TIM);  //开启定时器
		}
		if(SoftUSART->TX_Buffer.Write_Count >= sizeof(SoftUSART->TX_Buffer.Buffer))
		{
			SoftUSART->TX_Buffer.Write_Count = 0;
		}
		ret = 1;
	}
	else
	{
		ret = 0;
	}
	return ret;
}

/*字符串读取*/
uint16_t SoftUSART_Read(SoftUSART_TypeDef *SoftUSART,uint8_t *Dat,uint16_t Dat_Length)
{
	uint16_t cnt = 0;
	//如果一帧数据接收完成,返回要读取的大小
	if(SoftUSART->RX_Buffer.Flag & Flag_FlowDone)
	{
		for(cnt = 0; cnt < Dat_Length;cnt ++)
		{
			if(SoftUSART->RX_Buffer.RW_Subtract != 0)
			{
				Dat[cnt] = SoftUSART->RX_Buffer.Buffer[SoftUSART->RX_Buffer.Read_Count];
				SoftUSART->RX_Buffer.Read_Count += 1;
				SoftUSART->RX_Buffer.RW_Subtract -= 1;
				if(SoftUSART->RX_Buffer.Read_Count >= sizeof(SoftUSART->RX_Buffer.Buffer))
				{
					SoftUSART->RX_Buffer.Read_Count = 0;
				}
			}
			else
			{
				SoftUSART->RX_Buffer.Flag = Flag_Empty;
				break;
			}
		}
	}
	return cnt;
}

/*字符读取*/
uint8_t SoftUSART_ReadByte(SoftUSART_TypeDef *SoftUSART)
{
	uint8_t Dat = 0;
	if(SoftUSART->RX_Buffer.Flag & Flag_FlowDone)
	{
		if(SoftUSART->RX_Buffer.RW_Subtract != 0)
		{
			Dat = SoftUSART->RX_Buffer.Buffer[SoftUSART->RX_Buffer.Read_Count];
			SoftUSART->RX_Buffer.Read_Count += 1;
			SoftUSART->RX_Buffer.RW_Subtract -= 1;
			if(SoftUSART->RX_Buffer.Read_Count >= sizeof(SoftUSART->RX_Buffer.Buffer))
			{
				SoftUSART->RX_Buffer.Read_Count = 0;
			}
		}
		else
		{
			Dat = 0;
			SoftUSART->RX_Buffer.Flag = Flag_Empty;
		}
	}
	return Dat;
}

/*中断服务函数区*/
void SoftUSART_EXTI_ISR(SoftUSART_TypeDef *SoftUSART)
{
	//PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
	//	/*可专门封装一个函数实现打开关闭某通道的外部中断，传入参数用uint16_t GPIO_Pin*/
	RX_IT_OFF();  //清除外部中断触发
	SoftUSART_StartRecvConfig(SoftUSART);
	if(SoftUSART->RX_Buffer.Flag & Flag_IDLE)  //如果接收缓冲区为空闲
	{
		SoftUSART->RX_Buffer.Flag &=~ Flag_IDLE;
		SoftUSART->RX_Buffer.Flag |= Flag_Runing;
	}
	//PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
}

void SoftUSART_TIM_ISR(SoftUSART_TypeDef *SoftUSART)
{
	if(SoftUSART->RX_Buffer.Flag & Flag_Runing)
	{
	 	SoftUSART_RX_ISR(SoftUSART);
	}
	else if(SoftUSART->TX_Buffer.Flag & Flag_Runing)
	{
		//TIM_SET_CNT(SoftUSART->TIM,0);
	 	SoftUSART_TX_ISR(SoftUSART);
	}
	/*如果发送和接收都不在运行状态了就停止定时器*/
	if((!(SoftUSART->TX_Buffer.Flag & Flag_Runing)) && (!(SoftUSART->RX_Buffer.Flag & Flag_Runing)))
	{
		RX_IT_ON();  //开启接收中断
		TIM_OFF(SoftUSART->TIM);  //关闭定时器
	}
}

//用于定时器中断中的串口发送接收处理函数
void SoftUSART_RX_ISR(SoftUSART_TypeDef *SoftUSART)
{
	static uint8_t cnt = 0;
	static uint8_t RxData = 0;
	static uint8_t pin_read = 0;
	static SoftUSART_StateMachine_Def RxState = SoftUSART_StateMachine_Start;  //默认状态：停止

	// PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
	pin_read = PIN_READ(SoftUSART->RX_PORT,SoftUSART->RX_PIN)?0x80:0x00;
	// PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
	switch(RxState)
	{
		case SoftUSART_StateMachine_Start:
		{
			RX_IT_OFF();
			TIM_SET_ARR(SoftUSART->TIM,SoftUSART->BitTime);
			RxState = SoftUSART_StateMachine_Data;
			break;
		}
		case SoftUSART_StateMachine_Data:
		{
			RxData >>= 1;
			RxData |= pin_read;
			cnt += 1;

			if(cnt >= SoftUSART->DataBit)
			{
				if(SoftUSART->Parity == Parity_None)
				{
					RxState = SoftUSART_StateMachine_Stop;			
				}
				else
				{
					RxState = SoftUSART_StateMachine_Parity;
				}
				cnt = 0;
			}
			break;
		}
		case SoftUSART_StateMachine_Parity:
		{
			RxState = SoftUSART_StateMachine_Stop;
			break;
		}
		case SoftUSART_StateMachine_Stop:  //停止位状态
		{
			if(SoftUSART->RX_Buffer.RW_Subtract < sizeof(SoftUSART->RX_Buffer.Buffer))
			{
				SoftUSART->RX_Buffer.Buffer[SoftUSART->RX_Buffer.Write_Count] = RxData;
				SoftUSART->RX_Buffer.Write_Count += 1;
				SoftUSART->RX_Buffer.RW_Subtract += 1;
				if(SoftUSART->RX_Buffer.Write_Count >= sizeof(SoftUSART->RX_Buffer.Buffer))
				{
					SoftUSART->RX_Buffer.Write_Count = 0;
				}
			}
			else  //接收缓冲区溢出，
			{
				SoftUSART->RX_Buffer.Flag |= Flag_BufferFull;  //标记溢出
			}
			RxData = 0;
			RxState = SoftUSART_StateMachine_IDLEbit;  //下一个状态：空闲位
			break;
		}
		case SoftUSART_StateMachine_IDLEbit:  //空闲位状态
		{
			if(pin_read)  //空闲，跳到接收空闲函数，跳出后判断是否发送？在发送不停止否则停止定时器
			{
				SoftUSART->RX_Buffer.Flag &=~ Flag_Runing;
				SoftUSART->RX_Buffer.Flag |= Flag_FlowDone;  //置位数据流接收完成标志
				SoftUSART_RX_IDLE_ISR(SoftUSART);  //跳转到接收空闲处理函数
				if((SoftUSART->TX_Buffer.Flag & Flag_Runing) || (SoftUSART->TX_Buffer.Flag & Flag_Suspend))  //在发送状态或发送挂起
				{
					
					if(SoftUSART->TX_Buffer.Flag & Flag_Suspend)
					{
						SoftUSART->TX_Buffer.Flag |= Flag_Runing;  //发生挂起，置发送为运行状态
					}
				}
				else  //关闭定时器
				{
					// TIM_OFF(SoftUSART->TIM);  //停止定时器
				}
				RxState = SoftUSART_StateMachine_Start;  //跳转状态为开始状态
				
			}
			else  //不空闲，进入接收数据状态
			{
				RxState = SoftUSART_StateMachine_Data;
			}
			// PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
			// PIN_TOG(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
			break;
		}
		default:
		{
			RxState = SoftUSART_StateMachine_Start;
			break;
		}
	}
	
}

void SoftUSART_RX_IDLE_ISR(SoftUSART_TypeDef *SoftUSART)
{
	int dat = 0;
  	for(;;)
	{
		dat = SoftUSART_ReadByte(SoftUSART);
		if(dat == 0)
			break;
		SoftUSART_WriteByte(SoftUSART,dat);
    }
}

void SoftUSART_TX_ISR(SoftUSART_TypeDef *SoftUSART)
{
	static uint8_t cnt = 0;
	static uint8_t TxData = 0;
	static SoftUSART_StateMachine_Def TxState = SoftUSART_StateMachine_Stop;  //默认状态：停止

	switch(TxState)
	{
		case SoftUSART_StateMachine_Stop:
		{
			PIN_SET(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
			if(SoftUSART->TX_Buffer.RW_Subtract != 0)
			{
				TxState = SoftUSART_StateMachine_Start;  //有数据发送，产生停止位后设状态机为开始位状态
			}
			else
			{
				SoftUSART->TX_Buffer.Flag = Flag_Empty;  //标记发送完成
				if(SoftUSART->RX_Buffer.Flag & Flag_Runing)
				{
					
				}
				else
				{
					// TIM_OFF(SoftUSART->TIM);
				}
			}
			break;
		}
		case SoftUSART_StateMachine_Start:
		{
			PIN_RESET(SoftUSART->TX_PORT,SoftUSART->TX_PIN);  //拉低，产生开始位
			TxData = SoftUSART->TX_Buffer.Buffer[SoftUSART->TX_Buffer.Read_Count];
			SoftUSART->TX_Buffer.Read_Count += 1;
			SoftUSART->TX_Buffer.RW_Subtract -= 1;  //每读一个数据，将此计数器减一，表示队列出队
			cnt = 0;
			if(SoftUSART->TX_Buffer.Read_Count >= sizeof(SoftUSART->TX_Buffer.Buffer))  
			{
				SoftUSART->TX_Buffer.Read_Count = 0;
			}
			TxState = SoftUSART_StateMachine_Data;  //跳转状态：发送数据
			break;
		}
		case SoftUSART_StateMachine_Data:
		{
			if(cnt < SoftUSART->DataBit)
			{
				if(TxData & 0x01)
				{
					PIN_SET(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
				}
				else
				{
					PIN_RESET(SoftUSART->TX_PORT,SoftUSART->TX_PIN);
				}
				TxData >>= 1;
				cnt += 1;
			}
			else
			{
				if(SoftUSART->Parity == Parity_None)
				{
					PIN_SET(SoftUSART->TX_PORT,SoftUSART->TX_PIN);  //无校验位，则产生停止位
					if(SoftUSART->TX_Buffer.RW_Subtract != 0)
					{
					// for(uint8_t i=0;i<20;i++)
					// 	{
					// 		__NOP();
					// 	}
						TxState = SoftUSART_StateMachine_Start;  //有数据继续发送，产生停止位后设状态机为开始位状态			
					}
					else
					{
						TxState = SoftUSART_StateMachine_Stop;	//无数据需要发送，跳转到停止态	
					}
				}
				else
				{
					TxState = SoftUSART_StateMachine_Parity;
				}
			}
			break;
		}
		case SoftUSART_StateMachine_Parity:
		{ 
			TxState = SoftUSART_StateMachine_Stop;
			break;
		}
		case SoftUSART_StateMachine_IDLEbit:
		{
			SoftUSART->TX_Buffer.Flag = Flag_Empty;  //标记发送完成
			TxState = SoftUSART_StateMachine_Stop;
			break;
		}
		default:
		{
			TxState = SoftUSART_StateMachine_Stop;
			break;
		}
	}
	
}

/**/
void GPIO_A_10_CALLBACK(void)
{
	
}
void TIM2_IRQHandlerHandle(void)
{
	
}
void USART_Send(void)
{
	
}
